package com.hibernate.hrm.service.position;

import com.hibernate.hrm.dao.*;
import com.hibernate.hrm.entity.*;
import com.hibernate.hrm.entity.dto.position.PositionAddDTO;
import com.hibernate.hrm.entity.dto.position.PositionEditDTO;
import com.hibernate.hrm.entity.dto.position.PositionListDTO;
import com.hibernate.hrm.entity.dto.position.PositionQueryDTO;
import jakarta.persistence.EntityNotFoundException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class PositionServiceImpl implements PositionService {

    private final PositionRepository positionRepository;
    private final DepartmentRepository departmentRepository;
    private final OperateLogRepository operateLogRepository;
    private final RoleRepository roleRepository;
    private final UserRepository userRepository;
    private final HttpServletRequest request;

    @Override
    public Page<PositionListDTO> getPositionList(PositionQueryDTO queryDTO, User currentUser) {
        Pageable pageable = queryDTO.getPageable();

        // ROLE_DEPT_MGR 只能查看自己部门的职位
        if (currentUser.getRoleId().getRoleCode().equals("ROLE_DEPT_MGR")) {
            List<Department> accessibleDepartments = getAccessibleDepartments(currentUser);
            return positionRepository.findByDepartments(accessibleDepartments, pageable)
                    .map(PositionListDTO::fromEntity);
        }

        // 其他角色可以查看所有职位
        return positionRepository.findByFilters(
                queryDTO.getDepartmentId(),
                queryDTO.getPositionName(),
                queryDTO.getPositionCode(),
                pageable
        ).map(PositionListDTO::fromEntity);
    }

    @Override
    public List<Department> getAccessibleDepartments(User currentUser) {
        // ROLE_DEPT_MGR 只能管理自己部门
        if (currentUser.getRoleId().getRoleCode().equals("ROLE_DEPT_MGR")) {
            return List.of(currentUser.getDepartmentID());
        }
        // 其他角色可以查看所有部门
        return departmentRepository.findAll();
    }

    @Override
    @Transactional
    public void togglePositionStatus(Integer positionId, User operator) {
        Position position = positionRepository.findById(positionId)
                .orElseThrow(() -> new EntityNotFoundException("职位不存在"));

        // 检查是否有员工关联该职位
        long employeeCount = positionRepository.countActiveEmployeesByPosition(position);
        if (employeeCount > 0 && position.getStatus()) {
            throw new IllegalStateException("该职位存在"+employeeCount+"名关联员工，无法禁用");
        }

        boolean newStatus = !position.getStatus();
        position.setStatus(newStatus);
        position.setUpdateTime(LocalDateTime.now());
        positionRepository.save(position);

        // 记录操作日志
        recordPositionStatusChangeLog(operator, position, newStatus);
    }

    private void recordPositionStatusChangeLog(User operator, Position position, boolean newStatus) {
        OperateLog log = new OperateLog();
        log.setUserId(operator.getUserId());
        log.setOperateType("update");
        log.setOperateDetail(String.format(
                "用户[%s](ID:%d)%s了职位[%s](ID:%d)",
                operator.getRealName(),
                operator.getUserId(),
                newStatus ? "启用" : "禁用",
                position.getPositionName(),
                position.getPositionId()
        ));
        log.setOperateTime(LocalDateTime.now());
        log.setIpAddress(getClientIpAddress());
        log.setStatus(1);
        operateLogRepository.save(log);
    }

    @Override
    public List<Position> getAllPositionsForExport(User currentUser) {
        // ROLE_DEPT_MGR 只能导出自己部门的职位
        if (currentUser.getRoleId().getRoleCode().equals("ROLE_DEPT_MGR")) {
            return positionRepository.findByDepartmentID(currentUser.getDepartmentID());
        }

        // 其他角色可以导出所有职位
        return positionRepository.findAll();
    }

    @Override
    public Position getPositionById(Integer positionId, User currentUser) {
        Position position = positionRepository.findById(positionId)
                .orElseThrow(() -> new EntityNotFoundException("职位不存在"));

        // 部门经理只能查看自己部门的职位
        if (currentUser.getRoleId().getRoleCode().equals("ROLE_DEPT_MGR")
                && !position.getDepartmentID().getDepartmentID().equals(currentUser.getDepartmentID().getDepartmentID())) {
            throw new AccessDeniedException("无权查看该职位信息");
        }

        return position;
    }

    //编辑职位详情
    @Override
    public Position getPositionForEdit(Integer positionId) {
        return positionRepository.findById(positionId)
                .orElseThrow(() -> new EntityNotFoundException("职位不存在"));
    }

    @Override
    public List<Department> getAllActiveDepartments() {
        return departmentRepository.findByStatusTrue();
    }

    @Override
    public List<Role> getAllRoles() {
        return roleRepository.findAll();
    }

    @Override
    @Transactional
    public void updatePosition(Integer positionId, PositionEditDTO editDTO, User operator) {
        Position position = positionRepository.findById(positionId)
                .orElseThrow(() -> new EntityNotFoundException("职位不存在"));

        // 更新基本信息
        position.setPositionName(editDTO.getPositionName());
        position.setPositionCode(editDTO.getPositionCode());

        // 更新部门
        Department department = departmentRepository.findById(editDTO.getDepartmentID())
                .orElseThrow(() -> new EntityNotFoundException("部门不存在"));
        position.setDepartmentID(department);

        // 更新角色
        Role role = roleRepository.findById(editDTO.getPositionRoleID())
                .orElseThrow(() -> new EntityNotFoundException("角色不存在"));
        position.setPositionRoleID(role);

        // 更新薪资福利
        position.setMaxHeadCount(editDTO.getMaxHeadCount());
        position.setBaseSalary(editDTO.getBaseSalary());
        position.setAllowance(editDTO.getAllowance());
        position.setAnnualLeaveDays(editDTO.getAnnualLeaveDays());

        // 更新状态 - 确保无论true/false都能正确设置
        position.setStatus(editDTO.getStatus() != null ? editDTO.getStatus() : false);
        position.setUpdateTime(LocalDateTime.now());

        positionRepository.save(position);

        // 记录操作日志
        recordPositionUpdateLog(operator, position);
    }

    private void recordPositionUpdateLog(User operator, Position position) {
        OperateLog log = new OperateLog();
        log.setUserId(operator.getUserId());
        log.setOperateType("update");
        log.setOperateDetail(String.format(
                "用户[%s](ID:%d)更新了职位[%s](ID:%d)的信息",
                operator.getRealName(),
                operator.getUserId(),
                position.getPositionName(),
                position.getPositionId()
        ));
        log.setOperateTime(LocalDateTime.now());
        log.setIpAddress(getClientIpAddress());
        log.setStatus(1);
        operateLogRepository.save(log);
    }

    //新增职位
    @Override
    public void addPosition(PositionAddDTO positionAddDTO, User operator) {
        try {
            // 检查职位代码唯一性
            if (positionRepository.existsByPositionCode(positionAddDTO.getPositionCode())) {
                throw new IllegalArgumentException("职位代码已存在");
            }

            // 获取关联实体（使用getReferenceById减少数据库查询）
            Department department = departmentRepository.getReferenceById(positionAddDTO.getDepartmentId());
            Role role = roleRepository.getReferenceById(positionAddDTO.getPositionRoleId());

            // 构建并保存职位
            Position position = new Position();
            position.setPositionName(positionAddDTO.getPositionName());
            position.setPositionCode(positionAddDTO.getPositionCode());
            position.setDepartmentID(department);
            position.setPositionRoleID(role);
            position.setMaxHeadCount(positionAddDTO.getMaxHeadCount());
            position.setBaseSalary(positionAddDTO.getBaseSalary());
            position.setAllowance(positionAddDTO.getAllowance());
            position.setAnnualLeaveDays(positionAddDTO.getAnnualLeaveDays());
            position.setStatus(true);
            position.setCreateTime(LocalDateTime.now());

            // 显式保存并刷新
            Position savedPosition = positionRepository.saveAndFlush(position);

            // 记录日志
            recordPositionAddLog(operator, savedPosition);
        } catch (EntityNotFoundException e) {
            throw new IllegalArgumentException("关联的部门或角色不存在");
        }
    }

    private void recordPositionAddLog(User operator, Position position) {
        OperateLog log = new OperateLog();
        log.setUserId(operator.getUserId());
        log.setOperateType("create");
        log.setOperateDetail(String.format(
                "用户[%s](ID:%d)添加了职位[%s](ID:%d)到部门[%s](ID:%d)",
                operator.getRealName(),
                operator.getUserId(),
                position.getPositionName(),
                position.getPositionId(),
                position.getDepartmentID().getDepartmentName(),
                position.getDepartmentID().getDepartmentID()
        ));
        log.setOperateTime(LocalDateTime.now());
        log.setIpAddress(getClientIpAddress());
        log.setStatus(1);
        operateLogRepository.save(log);
    }

    //删除职位
    @Override
    @Transactional
    public void deletePosition(Integer positionId, User operator) throws Exception {
        Position position = positionRepository.findById(positionId)
                .orElseThrow(() -> new EntityNotFoundException("职位不存在"));

        // 检查是否有员工关联该职位
        long employeeCount = userRepository.countByJobPositionID(position);
        if (employeeCount > 0) {
            throw new IllegalStateException("该职位下仍有员工，无法删除");
        }

        // 删除职位
        positionRepository.delete(position);

        // 记录操作日志
        recordPositionDeleteLog(operator, position);
    }

    private void recordPositionDeleteLog(User operator, Position position) {
        OperateLog log = new OperateLog();
        log.setUserId(operator.getUserId());
        log.setOperateType("delete");
        log.setOperateDetail(String.format(
                "用户[%s](ID:%d)删除了职位[%s](ID:%d)",
                operator.getRealName(),
                operator.getUserId(),
                position.getPositionName(),
                position.getPositionId()
        ));
        log.setOperateTime(LocalDateTime.now());
        log.setIpAddress(getClientIpAddress());
        log.setStatus(1);
        operateLogRepository.save(log);
    }

    //获取IP地址
    private String getClientIpAddress() {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
